var mysql = require('mysql');

exports.fightForce = function(query, resp, callback) {
    if (isNaN(query.span)) {
        resp.code = 1; resp.desc = 'invalid params'; 
        callback(); return;
    }

    var minSid = +query.minSid;
    var maxSid = +query.maxSid;
    var minSection = +query.minSection || 0;
    var maxSection = +query.maxSection || 100;
    var span = (+query.span || 10) * 10000;
    var minFightForce = minSection * span;
    var maxFightForce = maxSection * span;
    

    async.each(gServers.getSids(minSid, maxSid), function(sid, cb) {
        var db = gServers.getGameDB(sid);
        if (!db) {
            cb(); return;
        }
    
        var dbUser = db.collection('user');
		var keyf = function(doc){
            return {'section':Math.floor(doc.status.fight_force/10000)};
        }
        var condition = {'status.fight_force':{'$gte':minFightForce, '$lt':maxFightForce}};
        var init = {'sum':0};
		var reduce = function(doc, prev) {
            prev.sum += 1;
        }
        dbUser.group(keyf, condition, init, reduce, function(err, results) {
            if (err || !results) {
                cb(util.format('server %d db error', sid)); return;
            }

            results.forEach(function(value){
                resp.data.push([sid, value.section, value.sum]);
            });
            cb();
        });
    }, function(err) {
        if (err) {
            resp.code = 1; resp.desc = err;
        }
        callback();
    });
}

exports.petLevel = function(query, resp, callback) {
    var minSid = +query.minSid;
    var maxSid = +query.maxSid;

    async.each(gServers.getSids(minSid, maxSid), function(sid, cb) {
        var db = gServers.getGameDB(sid);
        if (!db) {
            cb(); return;
        }
    
        var dbUser = db.collection('user');
        dbUser.group({'pet.level':1}, {'pet':{$exists:true}}, {count:0}, "function(obj,prev){prev.count += 1;}", function(err, results) {
            if (err || !results) {
                cb(util.format('server %d db error', sid)); return;
            }

            results.forEach(function(value){
                resp.data.push([sid, value['pet.level'], value.count]);
            });
            cb();
        });
    }, function(err) {
        if (err) {
            resp.code = 1; resp.desc = err;
        }
        callback();
    });
}

exports.role = function(query, resp, callback) {
    var minSid = +query.minSid;
    var maxSid = +query.maxSid;
    var minLevel = +query.minLevel || 50;
    var maxLevel = +query.maxLevel || UINT8_MAX;

    var condition = {'status.level': {'$gte': minLevel, '$lte': maxLevel}};
    if (query.hasOwnProperty('minTime')) {
        var timeCondition = {'$gte': +query.minTime};
        if (query.hasOwnProperty('maxTime')) {
            timeCondition['$lte'] = +query.maxTime;
        }
        condition['info.create'] = timeCondition;
    }

    async.each(gServers.getSids(minSid, maxSid), function(sid, cb) {
        var db = gServers.getGameDB(sid);
        if (!db) {
            cb(); return;
        }
    
        var serverResults = {
            sid: sid, 
            wing: {}, 
            star: {},
            soul: {},
            god: {},
            skill: {},
        };

        var cursor = db.collection('user').find(condition, {'role':1});
        cursor.each(function(err, item){
            if (cursor.isClosed()) {
                resp.data.push(serverResults);
                cb(); return;
            }

            var wingMarks = {};
            var starMarks = {};
            var soulMarks = {};
            var godMarks = {};
            var skillMarks = {};

            var roles = item.role;
            for (rid in roles) {
                var role = roles[rid];
                if (role.wing) {
                    var item = serverResults.wing[role.wing];
                    if (!item) {
                        item = {count:0, user:0};
                        serverResults.wing[role.wing] = item;
                    }
                    item.count++;
                    wingMarks[role.wing] = 1;
                }

                if (role.star) {
                    var item = serverResults.star[role.star];
                    if (!item) {
                        item = {count:0, user:0};
                        serverResults.star[role.star] = item;
                    }
                    item.count++;
                    starMarks[role.star] = 1;
                }

                if (role.soul) {
                    var section = Math.ceil(role.soul/20);
                    var item = serverResults.soul[section];
                    if (!item) {
                        item = {count:0, user:0};
                        serverResults.soul[section] = item;
                    }
                    item.count++;
                    soulMarks[section] = 1;
                }

                if (role.god) {
                    var item = serverResults.god[role.god];
                    if (!item) {
                        item = {count:0, user:0};
                        serverResults.god[role.god] = item;
                    }
                    item.count++;
                    godMarks[role.god] = 1;
                }
                
                var skillCount = 0;
                for (var skill in role.skill_levels) {
                    if (role.skill_levels[skill] >= 5) {
                        skillCount++;
                    }
                }
                if (skillCount) {
                    var item = serverResults.skill[skillCount];
                    if (!item) {
                        item = {count:0, user:0};
                        serverResults.skill[skillCount] = item;
                    }
                    item.count++;
                    skillMarks[skillCount] = 1;
                }
            }

            for (var value in wingMarks) {
                serverResults.wing[value].user++;
            }

            for (var value in starMarks) {
                serverResults.star[value].user++;
            }

            for (var value in soulMarks) {
                serverResults.soul[value].user++;
            }

            for (var value in godMarks) {
                serverResults.god[value].user++;
            }

            for (var value in skillMarks) {
                serverResults.skill[value].user++;
            }
        });
    }, function(err) {
        if (err) {
            resp.code = 1; resp.desc = err;
        }
        callback();
    });
}

exports.ride = function(query, resp, callback) {
    var minSid = +query.minSid;
    var maxSid = +query.maxSid;
    var minLevel = +query.minLevel || 50;
    var maxLevel = +query.maxLevel || UINT8_MAX;

    var condition = {'status.level': {'$gte': minLevel, '$lte': maxLevel}};
    if (query.hasOwnProperty('minTime')) {
        var timeCondition = {'$gte': +query.minTime};
        if (query.hasOwnProperty('maxTime')) {
            timeCondition['$lte'] = +query.maxTime;
        }
        condition['info.create'] = timeCondition;
    }

    async.each(gServers.getSids(minSid, maxSid), function(sid, cb) {
        var db = gServers.getGameDB(sid);
        if (!db) {
            cb(); return;
        }

        var serverResults = {
            sid: sid, 
            ride: {}, 
            seat: {}, 
            whip: {}, 
        };
    
        var cursor = db.collection('user').find(condition, {'role':1, 'ride.horse':1});
        cursor.each(function(err, item){
            if (cursor.isClosed()) {
                resp.data.push(serverResults);
                cb(); return;
            }
            
            var rideMarks = {};
            var seatMarks = {};
            var whipMarks = {};

            var roles = item.role;
            var horses = (item.ride ? item.ride.horse : {});
            for (rid in roles) {
                var role = roles[rid];
                if (!role.ride) continue;
                var ride = role.ride;
                var horse = horses[role.ride.horse];

                if (horse.level) {
                    var item = serverResults.ride[horse.level];
                    if (!item) {
                        item = {count:0, user:0};
                        serverResults.ride[horse.level] = item;
                    }
                    item.count++;
                    rideMarks[horse.level] = 1;
                }

                if (ride.seat) {
                    var item = serverResults.seat[ride.seat];
                    if (!item) {
                        item = {count:0, user:0};
                        serverResults.seat[ride.seat] = item;
                    }
                    item.count++;
                    seatMarks[ride.seat] = 1;
                }

                if (ride.whip) {
                    var item = serverResults.whip[ride.whip];
                    if (!item) {
                        item = {count:0, user:0};
                        serverResults.whip[ride.whip] = item;
                    }
                    item.count++;
                    whipMarks[ride.whip] = 1;
                }
            }

            for (var value in rideMarks) {
                serverResults.ride[value].user++;
            }

            for (var value in seatMarks) {
                serverResults.seat[value].user++;
            }

            for (var value in whipMarks) {
                serverResults.whip[value].user++;
            }
        });
    }, function(err) {
        if (err) {
            resp.code = 1; resp.desc = err;
        }
        callback();
    });
}

exports.worldBoss = function(query, resp, callback) {

    var bossArr = [];

    async.each(gServers.getSids(), function(sid, esCb) {
        var db = gServers.getGameDB(sid);
        if (!db) {
            esCb();
            return;
        }

        var dbWorld = db.collection("world");
        dbWorld.find({"_id":"world_boss"}).toArray(function(err, res){
            if (res && res.length > 0) {
                var curBoss = res[0]["world_boss"];
                bossArr.push([
                    sid,
                    curBoss['init_blood'] || 0,
                    curBoss['blood'] || 0,
                    curBoss['alive_time'] || 0,
                    curBoss['fight_times'] || 0,
                    curBoss['day'] || 0,
                    curBoss['today_id'] || 0,
                    curBoss['damage_factor'] || 0,
                ]);
            }
            esCb();
        });
    }, function(err){
        resp.code = 0;
        resp.data = bossArr;
        callback();
    });
};

exports.waigua = function(query, resp, callback){
    if (isNaN(query.minSid) || isNaN(query.maxSid)
        || isNaN(query.loginTimes) || isNaN(query.expScore)
        || isNaN(query.quarterActionScore)){
        resp.code = 1; resp.desc = 'invalid params';
        callback(); return;
    }

    var minSid = +query.minSid;
    var maxSid = +query.maxSid;
    var loginTimes = +query.loginTimes;
    var expScore = +query.expScore;
    var quarterActionScore = +query.quarterActionScore;

    var retArr = [];

    async.each(gServers.getSids(minSid, maxSid), function(sid, cb) {
        var db = gServers.getGameDB(sid);
        if (!db) {
            cb();
            return;
        }
        var dbUser = db.collection('user');
        var condition = {};
        if (loginTimes != 0)
            condition["daily_vars.login_times"] = {"$gte":loginTimes};
        if (expScore != 0)
            condition["daily_vars.except_score"] = {"$gte":expScore};
        if (quarterActionScore != 0)
            condition["quarterActionScore"] = {"$gte":quarterActionScore};
        dbUser.find(condition).toArray(function(err, res){
            if (!err && res){
                res.forEach(function(user){
                    retArr.push([
                        sid,
                        user._id,
                        user.daily_vars.login_times,
                        user.daily_vars.except_score,
                        user.quarterActionScore
                    ]);
                });
            }
            cb(null);
        });
    }, function(err) {
        if (err) {
            resp.code = 1; resp.desc = err;
        }
        resp.code = 0; resp.data = retArr;
        callback();
    });
};

exports.leagueLevel = function(query, resp, callback) {
    var minSid = +query.minSid;
    var maxSid = +query.maxSid;

    async.each(gServers.getSids(minSid, maxSid), function(sid, cb) {
        var db = gServers.getGameDB(sid);
        if (!db) {
            cb(); return;
        }

        db.collection('world').findOne({_id: 'league'}, {}, function(err, results) {
            if (err || !results) {
                cb(util.format('server %d db error', sid)); return;
            }
            
            var maxLevel = 10;
            var levels = new Array();
            levels.push(sid);
            for (var i = 0; i < maxLevel; ++i) {
                levels.push(0);
            }

            objectForEach(results.league, function(name, league) {
                levels[Math.min(league.level, maxLevel)]++;
            });
            resp.data.push(levels);
            cb();
        });
    }, function(err) {
        if (err) {
            resp.code = 1; resp.desc = err;
        }
        callback();
    });
}

exports.queryEmail = function(query, resp, callback){
    var openid = query.openid;
    var minTime = +query.minTime;
    var maxTime = +query.maxTime;
    var status = +query.status;

    var SQL = "";
    if (openid != "") {
        SQL = mysql.format("SELECT * FROM user WHERE openid=? AND stamp BETWEEN ? AND ? AND status = ?",
        [openid, minTime, maxTime, status]);
    } else {
        SQL = mysql.format("SELECT * FROM user WHERE stamp BETWEEN ? AND ? AND status = ?",
            [minTime, maxTime, status]);
    }

    var retArr = [];

    var dbConn = mysql.createConnection({
        host : config.mysql.gm.ip,
        port : config.mysql.gm.port,
        user : config.mysql.user,
        password : config.mysql.password,
        database : 'gamex',
        insecureAuth: true
    });

    dbConn.connect(function(err){
        if (err) {
            resp.code = 1;
            resp.desc = err;
            callback();
        } else {
            dbConn.query(
                SQL,
                function(err, rows){
                    if (err) {
                        resp.code = 1;
                        resp.err = err;
                    } else {
                        rows.forEach(function(item){
                            retArr.push([
                                item.openid,
                                item.mail,
                                item.verify_code,
                                item.stamp,
                                item.status
                            ]);
                        });
                        resp.code = 0;
                        resp.data = retArr;
                    }
                    callback();
                    dbConn.end();
                }
            );
        }
    });
};

exports.playerInfo = function(query, resp, callback){
    var openidStr = query.openids;

    // 检查参数
    if (!openidStr)
    {
        resp.code = 1; resp.desc = 'invalid params';
        callback(); return;
    }

    // 需要查询的玩家ID数组
    var openidArr = openidStr.split(",");

    var retData = [];
    var openidData = {};

    async.each(gServers.getSids(), function(sid, cb) {
        async.eachSeries(openidArr, function(openid, esCb){
            var db = gServers.getGameDB(sid);
            var uids = [];
            async.series([
                // 查询玩家角色
                function(scb) {
                    db.collection("plat").find({_id:openid}).toArray(function(err, arr){
                        if (err) LOG(err);
                        else {
                            arr.forEach(function(item){
                                uids.push(+item.uid);
                                if (item.uids) {
                                    uids = uids.concat(item.uids);
                                }
                            });
                        }
                        scb(null);
                    });
                },

                // 查询玩家数据
                function(scb) {
                    if (uids.length > 0) {
                        db.collection("user").find({_id:{"$in":uids}}).toArray(function(err, arr){
                            if (err) LOG(err);
                            else {
                                arr.forEach(function(item){
                                    openidData[openid] = openidData[openid] || {};
                                    openidData[openid][item._id] = {
                                        soul: item.status.soul  // 将魂
                                    };
                                });
                            }
                            scb(null);
                        });
                    } else {
                        scb(null);
                    }
                }
            ], function(err){
                esCb(null);
            });
        }, function(err){
            cb(null);
        });
    }, function(err){

        for (var openid in openidData) {
            if (openidData.hasOwnProperty(openid)) {
                var openidData_ = openidData[openid];
                for (var uid in openidData_) {
                    if (openidData_.hasOwnProperty(uid)) {
                        var uidData = openidData_[uid];
                        retData.push(openid + "," +
                            uid + "," +
                            uidData.soul);
                    }
                }
            }
        }

        resp.plain = true;
        resp.data = retData.join("\n");
        callback();

    });
};